#!/usr/bin/env python3  # 指定使用python3解释器运行此脚本
# -*- coding: utf-8 -*-  # 设置文件编码为UTF-8，支持中文字符

import json  # 导入json模块，用于数据的序列化和反序列化
import os  # 导入os模块，用于操作系统相关功能，如文件路径操作
import time  # 导入time模块，用于时间相关操作
from datetime import datetime, timedelta  # 从datetime模块导入datetime和timedelta类，用于日期时间处理
from typing import List, Dict, Optional  # 导入类型提示，用于代码的类型注解

class Equipment:  # 定义设备类，用于表示实验室设备对象
    def __init__(self, equipment_id: str, name: str, category: str, model: str, lab_id: str,   # 构造函数，初始化设备对象
                 purchase_date: str = "", price: float = 0.0, status: str = "可用"):  # 设置默认参数值
        self.equipment_id = equipment_id  # 设置设备ID属性
        self.name = name  # 设置设备名称属性
        self.category = category  # 设置设备类别属性
        self.model = model  # 设置设备型号属性
        self.lab_id = lab_id  # 设置所属实验室ID属性
        self.purchase_date = purchase_date  # 设置购买日期属性
        self.price = price  # 设置设备价格属性
        self.status = status  # 设置设备状态属性
        self.create_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")  # 获取当前时间并格式化为字符串，作为创建时间
    
    def to_dict(self) -> dict:  # 定义方法将设备对象转换为字典格式
        return {  # 返回包含所有设备属性的字典
            'equipment_id': self.equipment_id,  # 设备ID键值对
            'name': self.name,  # 设备名称键值对
            'category': self.category,  # 设备类别键值对
            'model': self.model,  # 设备型号键值对
            'lab_id': self.lab_id,  # 实验室ID键值对
            'purchase_date': self.purchase_date,  # 购买日期键值对
            'price': self.price,  # 设备价格键值对
            'status': self.status,  # 设备状态键值对
            'create_time': self.create_time  # 创建时间键值对
        }
    
    @classmethod  # 类方法装饰器，表示这是一个类方法
    def from_dict(cls, data: dict):  # 定义类方法，从字典数据创建设备对象
        equipment = cls(  # 调用类构造函数创建设备实例
            data['equipment_id'],  # 从字典获取设备ID
            data['name'],  # 从字典获取设备名称
            data['category'],  # 从字典获取设备类别
            data['model'],  # 从字典获取设备型号
            data['lab_id'],  # 从字典获取实验室ID
            data.get('purchase_date', ''),  # 从字典获取购买日期，如果不存在则使用空字符串
            data.get('price', 0.0),  # 从字典获取价格，如果不存在则使用0.0
            data.get('status', '可用')  # 从字典获取状态，如果不存在则使用"可用"
        )
        equipment.create_time = data.get('create_time', datetime.now().strftime("%Y-%m-%d %H:%M:%S"))  # 设置创建时间，如果不存在则使用当前时间
        return equipment  # 返回创建的设备对象
    
    def __str__(self) -> str:  # 定义字符串表示方法，用于打印设备对象
        return f"设备ID：{self.equipment_id} | 名称：{self.name} | 型号：{self.model} | 状态：{self.status}"  # 返回格式化的设备信息字符串

class Laboratory:  # 定义实验室类，用于表示实验室对象
    def __init__(self, lab_id: str, name: str, location: str, manager: str, capacity: int, description: str = ""):  # 构造函数，初始化实验室对象
        self.lab_id = lab_id  # 设置实验室ID属性
        self.name = name  # 设置实验室名称属性
        self.location = location  # 设置实验室位置属性
        self.manager = manager  # 设置实验室管理员属性
        self.capacity = capacity  # 设置实验室容量属性
        self.description = description  # 设置实验室描述属性
        self.create_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")  # 获取当前时间并格式化为字符串，作为创建时间
    
    def to_dict(self) -> dict:  # 定义方法将实验室对象转换为字典格式
        return {  # 返回包含所有实验室属性的字典
            'lab_id': self.lab_id,  # 实验室ID键值对
            'name': self.name,  # 实验室名称键值对
            'location': self.location,  # 实验室位置键值对
            'manager': self.manager,  # 实验室管理员键值对
            'capacity': self.capacity,  # 实验室容量键值对
            'description': self.description,  # 实验室描述键值对
            'create_time': self.create_time  # 创建时间键值对
        }
    
    @classmethod  # 类方法装饰器，表示这是一个类方法
    def from_dict(cls, data: dict):  # 定义类方法，从字典数据创建实验室对象
        lab = cls(  # 调用类构造函数创建实验室实例
            data['lab_id'],  # 从字典获取实验室ID
            data['name'],  # 从字典获取实验室名称
            data['location'],  # 从字典获取实验室位置
            data['manager'],  # 从字典获取实验室管理员
            data.get('capacity', 0),  # 从字典获取容量，如果不存在则使用0
            data.get('description', '')  # 从字典获取描述，如果不存在则使用空字符串
        )
        lab.create_time = data.get('create_time', datetime.now().strftime("%Y-%m-%d %H:%M:%S"))  # 设置创建时间，如果不存在则使用当前时间
        return lab  # 返回创建的实验室对象
    
    def __str__(self) -> str:  # 定义字符串表示方法，用于打印实验室对象
        return f"实验室ID：{self.lab_id} | 名称：{self.name} | 位置：{self.location} | 管理员：{self.manager}"  # 返回格式化的实验室信息字符串

class BorrowRecord:  # 定义借用记录类，用于表示设备借用记录对象
    def __init__(self, record_id: str, equipment_id: str, borrower: str, borrow_date: str,   # 构造函数，初始化借用记录对象
                 expected_return: str, actual_return: str = "", purpose: str = "", remarks: str = ""):  # 设置默认参数值
        self.record_id = record_id  # 设置记录ID属性
        self.equipment_id = equipment_id  # 设置设备ID属性
        self.borrower = borrower  # 设置借用人属性
        self.borrow_date = borrow_date  # 设置借用日期属性
        self.expected_return = expected_return  # 设置预期归还日期属性
        self.actual_return = actual_return  # 设置实际归还日期属性
        self.purpose = purpose  # 设置借用目的属性
        self.remarks = remarks  # 设置备注属性
        self.status = "借用中" if not actual_return else "已归还"  # 根据是否有实际归还日期设置状态
        self.create_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")  # 获取当前时间并格式化为字符串，作为创建时间
    
    def to_dict(self) -> dict:  # 定义方法将借用记录对象转换为字典格式
        return {  # 返回包含所有借用记录属性的字典
            'record_id': self.record_id,  # 记录ID键值对
            'equipment_id': self.equipment_id,  # 设备ID键值对
            'borrower': self.borrower,  # 借用人键值对
            'borrow_date': self.borrow_date,  # 借用日期键值对
            'expected_return': self.expected_return,  # 预期归还日期键值对
            'actual_return': self.actual_return,  # 实际归还日期键值对
            'purpose': self.purpose,  # 借用目的键值对
            'remarks': self.remarks,  # 备注键值对
            'status': self.status,  # 状态键值对
            'create_time': self.create_time  # 创建时间键值对
        }
    
    @classmethod  # 类方法装饰器，表示这是一个类方法
    def from_dict(cls, data: dict):  # 定义类方法，从字典数据创建借用记录对象
        record = cls(  # 调用类构造函数创建借用记录实例
            data['record_id'],  # 从字典获取记录ID
            data['equipment_id'],  # 从字典获取设备ID
            data['borrower'],  # 从字典获取借用人
            data['borrow_date'],  # 从字典获取借用日期
            data['expected_return'],  # 从字典获取预期归还日期
            data.get('actual_return', ''),  # 从字典获取实际归还日期，如果不存在则使用空字符串
            data.get('purpose', ''),  # 从字典获取借用目的，如果不存在则使用空字符串
            data.get('remarks', '')  # 从字典获取备注，如果不存在则使用空字符串
        )
        record.status = data.get('status', '借用中')  # 设置状态，如果不存在则使用"借用中"
        record.create_time = data.get('create_time', datetime.now().strftime("%Y-%m-%d %H:%M:%S"))  # 设置创建时间，如果不存在则使用当前时间
        return record  # 返回创建的借用记录对象
    
    def __str__(self) -> str:  # 定义字符串表示方法，用于打印借用记录对象
        return f"记录ID：{self.record_id} | 设备ID：{self.equipment_id} | 借用人：{self.borrower} | 状态：{self.status}"  # 返回格式化的借用记录信息字符串

class LabEquipmentSystem:  # 定义实验室设备管理系统主类
    
    def __init__(self):  # 构造函数，初始化系统对象
        self.equipments: Dict[str, Equipment] = {}  # 初始化设备字典，键为设备ID，值为设备对象
        self.laboratories: Dict[str, Laboratory] = {}  # 初始化实验室字典，键为实验室ID，值为实验室对象
        self.borrow_records: Dict[str, BorrowRecord] = {}  # 初始化借用记录字典，键为记录ID，值为借用记录对象
        self.data_file = "lab_equipment_data.txt"  # 设置数据文件名
        self.load_data()  # 调用加载数据方法，从文件中读取已保存的数据
    
    def save_data(self):  # 定义保存数据方法，将内存中的数据保存到文件
        try:  # 使用try-except结构处理可能的异常
            data = {  # 创建包含所有数据的字典
                'equipments': {eid: equipment.to_dict() for eid, equipment in self.equipments.items()},  # 将设备字典转换为可序列化的格式
                'laboratories': {lid: lab.to_dict() for lid, lab in self.laboratories.items()},  # 将实验室字典转换为可序列化的格式
                'borrow_records': {rid: record.to_dict() for rid, record in self.borrow_records.items()}  # 将借用记录字典转换为可序列化的格式
            }
            with open(self.data_file, 'w', encoding='utf-8') as f:  # 以写入模式打开数据文件，指定UTF-8编码
                json.dump(data, f, ensure_ascii=False, indent=2)  # 将数据以JSON格式写入文件，ensure_ascii=False支持中文，indent=2美化格式
            print("数据保存成功！")
        except Exception as e:  # 捕获所有异常
            print(f"数据保存失败：{e}")  # 打印错误信息
    
    def load_data(self):  # 定义加载数据方法，从文件中读取数据到内存
        try:  # 使用try-except结构处理可能的异常
            if os.path.exists(self.data_file):  # 检查数据文件是否存在
                with open(self.data_file, 'r', encoding='utf-8') as f:  # 以读取模式打开数据文件，指定UTF-8编码
                    data = json.load(f)  # 从文件中加载JSON数据
                
                if 'equipments' in data:  # 检查数据中是否包含设备信息
                    for eid, equipment_data in data['equipments'].items():  # 遍历设备数据
                        self.equipments[eid] = Equipment.from_dict(equipment_data)  # 从字典数据创建设备对象并存储
                
                if 'laboratories' in data:  # 检查数据中是否包含实验室信息
                    for lid, lab_data in data['laboratories'].items():  # 遍历实验室数据
                        self.laboratories[lid] = Laboratory.from_dict(lab_data)  # 从字典数据创建实验室对象并存储
                
                if 'borrow_records' in data:  # 检查数据中是否包含借用记录信息
                    for rid, record_data in data['borrow_records'].items():  # 遍历借用记录数据
                        self.borrow_records[rid] = BorrowRecord.from_dict(record_data)  # 从字典数据创建借用记录对象并存储
                
                print("数据加载成功！")
        except Exception as e:  # 捕获所有异常
            print(f"数据加载失败：{e}")  # 打印错误信息
    
    def add_equipment(self):  # 定义添加设备方法
        print("\n=== 添加设备 ===")
        equipment_id = input("请输入设备ID：").strip()  # 获取用户输入的设备ID并去除首尾空格
        
        if equipment_id in self.equipments:  # 检查设备ID是否已存在
            print("该设备ID已存在！")
            return  # 如果已存在则退出方法
        
        name = input("请输入设备名称：").strip()  # 获取用户输入的设备名称并去除首尾空格
        category = input("请输入设备类别：").strip()  # 获取用户输入的设备类别并去除首尾空格
        model = input("请输入设备型号：").strip()  # 获取用户输入的设备型号并去除首尾空格
        lab_id = input("请输入所属实验室ID：").strip()  # 获取用户输入的实验室ID并去除首尾空格
        
        if lab_id and lab_id not in self.laboratories:  # 如果输入了实验室ID但该ID不存在
            print("实验室ID不存在！请先添加实验室。")
            return  # 退出方法
        
        purchase_date = input("请输入购买日期（YYYY-MM-DD，可选）：").strip()  # 获取用户输入的购买日期并去除首尾空格
        price_input = input("请输入设备价格（可选）：").strip()  # 获取用户输入的设备价格并去除首尾空格
        
        try:  # 尝试转换价格为浮点数
            price = float(price_input) if price_input else 0.0  # 如果输入了价格则转换为浮点数，否则使用0.0
        except ValueError:  # 如果转换失败
            price = 0.0  # 使用默认值0.0
        
        if not all([equipment_id, name, category, model]):  # 检查必填字段是否都已填写
            print("设备ID、名称、类别、型号不能为空！")
            return  # 如果有空值则退出方法
        
        equipment = Equipment(equipment_id, name, category, model, lab_id, purchase_date, price)  # 创建设备对象
        self.equipments[equipment_id] = equipment  # 将设备对象添加到设备字典中
        print(f"设备 {name} 添加成功！")
        self.save_data()  # 保存数据到文件
    
    def delete_equipment(self):  # 定义删除设备方法
        print("\n=== 删除设备 ===")
        equipment_id = input("请输入要删除的设备ID：").strip()  # 获取用户输入的要删除的设备ID并去除首尾空格
        
        if equipment_id not in self.equipments:  # 检查设备ID是否存在
            print("设备ID不存在！")
            return  # 如果不存在则退出方法
        
        equipment = self.equipments[equipment_id]  # 获取要删除的设备对象
        
        active_borrows = [r for r in self.borrow_records.values()   # 查找该设备的活跃借用记录
                         if r.equipment_id == equipment_id and r.status == "借用中"]  # 筛选出状态为"借用中"的记录
        if active_borrows:  # 如果存在活跃的借用记录
            print("该设备仍有借用记录未归还，无法删除！")
            return  # 退出方法，不允许删除
        
        confirm = input(f"确认删除设备 {equipment.name}（{equipment_id}）？(y/n)：").strip().lower()  # 获取用户确认，转换为小写
        
        if confirm == 'y':  # 如果用户确认删除
            to_delete = [rid for rid, record in self.borrow_records.items() if record.equipment_id == equipment_id]  # 找出所有与该设备相关的借用记录ID
            for rid in to_delete:  # 遍历要删除的记录ID
                del self.borrow_records[rid]  # 删除借用记录
            
            del self.equipments[equipment_id]  # 从设备字典中删除该设备
            print(f"设备 {equipment.name} 删除成功！")
            self.save_data()  # 保存数据到文件
        else:  # 如果用户取消删除
            print("取消删除。")
    
    def update_equipment(self):  # 定义修改设备信息方法
        print("\n=== 修改设备信息 ===")
        equipment_id = input("请输入要修改的设备ID：").strip()  # 获取用户输入的要修改的设备ID并去除首尾空格
        
        if equipment_id not in self.equipments:  # 检查设备ID是否存在
            print("设备ID不存在！")
            return  # 如果不存在则退出方法
        
        equipment = self.equipments[equipment_id]  # 获取要修改的设备对象
        print(f"当前设备信息：{equipment}")  # 显示当前设备信息
        
        print("\n请输入新信息（直接回车保持原值）：")
        name = input(f"设备名称（{equipment.name}）：").strip()  # 获取新的设备名称，显示当前值作为提示
        category = input(f"设备类别（{equipment.category}）：").strip()  # 获取新的设备类别，显示当前值作为提示
        model = input(f"设备型号（{equipment.model}）：").strip()  # 获取新的设备型号，显示当前值作为提示
        lab_id = input(f"所属实验室ID（{equipment.lab_id}）：").strip()  # 获取新的实验室ID，显示当前值作为提示
        purchase_date = input(f"购买日期（{equipment.purchase_date}）：").strip()  # 获取新的购买日期，显示当前值作为提示
        price_input = input(f"设备价格（{equipment.price}）：").strip()  # 获取新的设备价格，显示当前值作为提示
        
        print("设备状态：")  # 显示状态选择菜单
        print("1. 可用")
        print("2. 借用中")
        print("3. 维修中")
        print("4. 已报废")
        status_choice = input(f"状态（当前：{equipment.status}）：").strip()  # 获取状态选择，显示当前状态
        status_map = {'1': '可用', '2': '借用中', '3': '维修中', '4': '已报废'}  # 创建状态映射字典
        status = status_map.get(status_choice, equipment.status)  # 根据用户选择获取状态，如果无效则保持原状态
        
        if lab_id and lab_id not in self.laboratories and lab_id != equipment.lab_id:  # 如果输入了新的实验室ID且该ID不存在且不等于原ID
            print("实验室ID不存在！")
            return  # 退出方法
        
        if name:  # 如果输入了新名称
            equipment.name = name  # 更新设备名称
        if category:  # 如果输入了新类别
            equipment.category = category  # 更新设备类别
        if model:  # 如果输入了新型号
            equipment.model = model  # 更新设备型号
        if lab_id:  # 如果输入了新实验室ID
            equipment.lab_id = lab_id  # 更新实验室ID
        if purchase_date or purchase_date == "":  # 如果输入了新购买日期或输入空字符串清空
            equipment.purchase_date = purchase_date  # 更新购买日期
        if price_input:  # 如果输入了新价格
            try:  # 尝试转换价格
                equipment.price = float(price_input)  # 更新设备价格
            except ValueError:  # 如果转换失败
                print("价格必须为数字！")
        if status_choice:  # 如果选择了新状态
            equipment.status = status  # 更新设备状态
        
        print("设备信息修改成功！")
        self.save_data()  # 保存数据到文件
    
    def search_equipment(self):  # 定义查询设备方法
        print("\n=== 查询设备 ===")
        print("1. 按设备ID查询")  # 显示查询选项1
        print("2. 按设备名称查询")  # 显示查询选项2
        print("3. 按设备类别查询")  # 显示查询选项3
        print("4. 按实验室查询")  # 显示查询选项4
        print("5. 按状态查询")  # 显示查询选项5
        
        choice = input("请选择查询方式：").strip()  # 获取用户选择的查询方式并去除首尾空格
        
        if choice == '1':  # 如果选择按设备ID查询
            equipment_id = input("请输入设备ID：").strip()  # 获取用户输入的设备ID并去除首尾空格
            if equipment_id in self.equipments:  # 检查设备ID是否存在
                print(f"\n查询结果：")
                self._display_equipment_detail(self.equipments[equipment_id])  # 显示设备详细信息
            else:  # 如果设备ID不存在
                print("未找到该设备ID。")
        
        elif choice == '2':  # 如果选择按设备名称查询
            name = input("请输入设备名称：").strip()  # 获取用户输入的设备名称并去除首尾空格
            results = [eq for eq in self.equipments.values() if name in eq.name]  # 查找名称中包含输入内容的设备
            self._display_equipment_results(results, "名称")  # 显示查询结果
        
        elif choice == '3':  # 如果选择按设备类别查询
            category = input("请输入设备类别：").strip()  # 获取用户输入的设备类别并去除首尾空格
            results = [eq for eq in self.equipments.values() if category in eq.category]  # 查找类别中包含输入内容的设备
            self._display_equipment_results(results, "类别")  # 显示查询结果
        
        elif choice == '4':  # 如果选择按实验室查询
            lab_id = input("请输入实验室ID：").strip()  # 获取用户输入的实验室ID并去除首尾空格
            results = [eq for eq in self.equipments.values() if eq.lab_id == lab_id]  # 查找属于指定实验室的设备
            self._display_equipment_results(results, "实验室")  # 显示查询结果
        
        elif choice == '5':  # 如果选择按状态查询
            print("请选择设备状态：")  # 显示状态选择菜单
            print("1. 可用")
            print("2. 借用中")
            print("3. 维修中")
            print("4. 已报废")
            status_choice = input("请选择状态：").strip()  # 获取用户选择的状态并去除首尾空格
            status_map = {'1': '可用', '2': '借用中', '3': '维修中', '4': '已报废'}  # 创建状态映射字典
            status = status_map.get(status_choice)  # 根据用户选择获取对应的状态字符串
            
            if status:  # 如果状态选择有效
                results = [eq for eq in self.equipments.values() if eq.status == status]  # 查找指定状态的设备
                self._display_equipment_results(results, f"状态（{status}）")  # 显示查询结果
            else:  # 如果状态选择无效
                print("无效的状态选择！")
        
        else:  # 如果选择无效
            print("无效的选择！")
    
    def _display_equipment_detail(self, equipment: Equipment):  # 定义显示设备详细信息的私有方法
        lab_name = ""  # 初始化实验室名称为空字符串
        if equipment.lab_id and equipment.lab_id in self.laboratories:  # 如果设备有实验室ID且该实验室存在
            lab_name = self.laboratories[equipment.lab_id].name  # 获取实验室名称
        
        print(f"设备ID：{equipment.equipment_id}")  # 打印设备ID
        print(f"设备名称：{equipment.name}")  # 打印设备名称
        print(f"设备类别：{equipment.category}")  # 打印设备类别
        print(f"设备型号：{equipment.model}")  # 打印设备型号
        print(f"所属实验室：{lab_name}（{equipment.lab_id}）")  # 打印所属实验室信息
        print(f"购买日期：{equipment.purchase_date}")  # 打印购买日期
        print(f"设备价格：{equipment.price}")  # 打印设备价格
        print(f"设备状态：{equipment.status}")  # 打印设备状态
        print(f"创建时间：{equipment.create_time}")  # 打印创建时间
    
    def _display_equipment_results(self, results: List[Equipment], search_type: str):  # 定义显示设备查询结果的私有方法
        if results:  # 如果有查询结果
            print(f"\n按{search_type}查询结果（共{len(results)}条）：")  # 打印结果统计信息
            for i, equipment in enumerate(results, 1):  # 遍历结果列表，从1开始编号
                print(f"{i}. {equipment}")  # 打印每个设备的基本信息
        else:  # 如果没有查询结果
            print(f"未找到匹配的设备。")
    
    def list_all_equipments(self):  # 定义列出所有设备的方法
        print("\n=== 所有设备列表 ===")
        if not self.equipments:  # 如果设备字典为空
            print("暂无设备数据。")
            return  # 退出方法
        
        print(f"共有 {len(self.equipments)} 台设备：")  # 打印设备总数
        for i, equipment in enumerate(self.equipments.values(), 1):  # 遍历所有设备，从1开始编号
            print(f"{i}. {equipment}")  # 打印每个设备的基本信息
    
    def add_laboratory(self):  # 定义添加实验室方法
        print("\n=== 添加实验室 ===")
        lab_id = input("请输入实验室ID：").strip()  # 获取用户输入的实验室ID并去除首尾空格
        
        if lab_id in self.laboratories:  # 检查实验室ID是否已存在
            print("该实验室ID已存在！")
            return  # 如果已存在则退出方法
        
        name = input("请输入实验室名称：").strip()  # 获取用户输入的实验室名称并去除首尾空格
        location = input("请输入实验室位置：").strip()  # 获取用户输入的实验室位置并去除首尾空格
        manager = input("请输入管理员：").strip()  # 获取用户输入的管理员并去除首尾空格
        capacity_input = input("请输入容量：").strip()  # 获取用户输入的容量并去除首尾空格
        description = input("请输入描述（可选）：").strip()  # 获取用户输入的描述并去除首尾空格
        
        try:  # 尝试转换容量为整数
            capacity = int(capacity_input) if capacity_input else 0  # 如果输入了容量则转换为整数，否则使用0
        except ValueError:  # 如果转换失败
            capacity = 0  # 使用默认值0
        
        if not all([lab_id, name, location, manager]):  # 检查必填字段是否都已填写
            print("实验室ID、名称、位置、管理员不能为空！")
            return  # 如果有空值则退出方法
        
        laboratory = Laboratory(lab_id, name, location, manager, capacity, description)  # 创建实验室对象
        self.laboratories[lab_id] = laboratory  # 将实验室对象添加到实验室字典中
        print(f"实验室 {name} 添加成功！")
        self.save_data()  # 保存数据到文件
    
    def delete_laboratory(self):  # 定义删除实验室方法
        print("\n=== 删除实验室 ===")
        lab_id = input("请输入要删除的实验室ID：").strip()  # 获取用户输入的要删除的实验室ID并去除首尾空格
        
        if lab_id not in self.laboratories:  # 检查实验室ID是否存在
            print("实验室ID不存在！")
            return  # 如果不存在则退出方法
        
        equipments_in_lab = [eq for eq in self.equipments.values() if eq.lab_id == lab_id]  # 查找该实验室中的所有设备
        if equipments_in_lab:  # 如果实验室中还有设备
            print(f"该实验室仍有 {len(equipments_in_lab)} 台设备，无法删除！")
            return  # 退出方法，不允许删除
        
        laboratory = self.laboratories[lab_id]  # 获取要删除的实验室对象
        confirm = input(f"确认删除实验室 {laboratory.name}（{lab_id}）？(y/n)：").strip().lower()  # 获取用户确认，转换为小写
        
        if confirm == 'y':  # 如果用户确认删除
            del self.laboratories[lab_id]  # 从实验室字典中删除该实验室
            print(f"实验室 {laboratory.name} 删除成功！")
            self.save_data()  # 保存数据到文件
        else:  # 如果用户取消删除
            print("取消删除。")
    
    def update_laboratory(self):  # 定义修改实验室信息方法
        print("\n=== 修改实验室信息 ===")
        lab_id = input("请输入要修改的实验室ID：").strip()  # 获取用户输入的要修改的实验室ID并去除首尾空格
        
        if lab_id not in self.laboratories:  # 检查实验室ID是否存在
            print("实验室ID不存在！")
            return  # 如果不存在则退出方法
        
        laboratory = self.laboratories[lab_id]  # 获取要修改的实验室对象
        print(f"当前实验室信息：{laboratory}")  # 显示当前实验室信息
        
        print("\n请输入新信息（直接回车保持原值）：")
        name = input(f"实验室名称（{laboratory.name}）：").strip()  # 获取新的实验室名称，显示当前值作为提示
        location = input(f"实验室位置（{laboratory.location}）：").strip()  # 获取新的实验室位置，显示当前值作为提示
        manager = input(f"管理员（{laboratory.manager}）：").strip()  # 获取新的管理员，显示当前值作为提示
        capacity_input = input(f"容量（{laboratory.capacity}）：").strip()  # 获取新的容量，显示当前值作为提示
        description = input(f"描述（{laboratory.description}）：").strip()  # 获取新的描述，显示当前值作为提示
        
        if name:  # 如果输入了新名称
            laboratory.name = name  # 更新实验室名称
        if location:  # 如果输入了新位置
            laboratory.location = location  # 更新实验室位置
        if manager:  # 如果输入了新管理员
            laboratory.manager = manager  # 更新管理员
        if capacity_input:  # 如果输入了新容量
            try:  # 尝试转换容量
                laboratory.capacity = int(capacity_input)  # 更新实验室容量
            except ValueError:  # 如果转换失败
                print("容量必须为数字！")
        if description or description == "":  # 如果输入了新描述或输入空字符串清空
            laboratory.description = description  # 更新实验室描述
        
        print("实验室信息修改成功！")
        self.save_data()  # 保存数据到文件
    
    def list_all_laboratories(self):  # 定义列出所有实验室的方法
        print("\n=== 所有实验室列表 ===")
        if not self.laboratories:  # 如果实验室字典为空
            print("暂无实验室数据。")
            return  # 退出方法
        
        print(f"共有 {len(self.laboratories)} 个实验室：")  # 打印实验室总数
        for i, lab in enumerate(self.laboratories.values(), 1):  # 遍历所有实验室，从1开始编号
            equipment_count = len([eq for eq in self.equipments.values() if eq.lab_id == lab.lab_id])  # 计算该实验室的设备数量
            print(f"{i}. {lab} | 设备数量：{equipment_count}")  # 打印实验室基本信息和设备数量
    
    def borrow_equipment(self):  # 定义设备借用方法
        print("\n=== 设备借用 ===")
        equipment_id = input("请输入要借用的设备ID：").strip()  # 获取用户输入的要借用的设备ID并去除首尾空格
        
        if equipment_id not in self.equipments:  # 检查设备ID是否存在
            print("设备ID不存在！")
            return  # 如果不存在则退出方法
        
        equipment = self.equipments[equipment_id]  # 获取要借用的设备对象
        if equipment.status != "可用":  # 检查设备状态是否为可用
            print(f"设备状态为 {equipment.status}，无法借用！")
            return  # 如果不可用则退出方法
        
        record_id = input("请输入借用记录ID：").strip()  # 获取用户输入的借用记录ID并去除首尾空格
        if record_id in self.borrow_records:  # 检查记录ID是否已存在
            print("该记录ID已存在！")
            return  # 如果已存在则退出方法
        
        borrower = input("请输入借用人：").strip()  # 获取用户输入的借用人并去除首尾空格
        borrow_date = input("请输入借用日期（YYYY-MM-DD，默认今天）：").strip()  # 获取用户输入的借用日期并去除首尾空格
        if not borrow_date:  # 如果没有输入借用日期
            borrow_date = datetime.now().strftime("%Y-%m-%d")  # 使用今天的日期
        
        days_input = input("请输入预计借用天数（默认7天）：").strip()  # 获取用户输入的借用天数并去除首尾空格
        try:  # 尝试转换天数为整数
            days = int(days_input) if days_input else 7  # 如果输入了天数则转换为整数，否则使用7天
        except ValueError:  # 如果转换失败
            days = 7  # 使用默认值7天
        
        expected_return = (datetime.strptime(borrow_date, "%Y-%m-%d") + timedelta(days=days)).strftime("%Y-%m-%d")  # 计算预期归还日期
        purpose = input("请输入借用用途（可选）：").strip()  # 获取用户输入的借用用途并去除首尾空格
        remarks = input("请输入备注（可选）：").strip()  # 获取用户输入的备注并去除首尾空格
        
        if not all([record_id, borrower]):  # 检查必填字段是否都已填写
            print("记录ID和借用人不能为空！")
            return  # 如果有空值则退出方法
        
        borrow_record = BorrowRecord(record_id, equipment_id, borrower, borrow_date, expected_return, "", purpose, remarks)  # 创建借用记录对象
        self.borrow_records[record_id] = borrow_record  # 将借用记录对象添加到借用记录字典中
        equipment.status = "借用中"  # 更新设备状态为借用中
        
        print(f"设备 {equipment.name} 借用成功！预计归还日期：{expected_return}")
        self.save_data()  # 保存数据到文件
    
    def return_equipment(self):  # 定义设备归还方法
        print("\n=== 设备归还 ===")
        record_id = input("请输入借用记录ID：").strip()  # 获取用户输入的借用记录ID并去除首尾空格
        
        if record_id not in self.borrow_records:  # 检查借用记录ID是否存在
            print("借用记录ID不存在！")
            return  # 如果不存在则退出方法
        
        record = self.borrow_records[record_id]  # 获取借用记录对象
        if record.status == "已归还":  # 检查记录状态是否已归还
            print("该设备已经归还！")
            return  # 如果已归还则退出方法
        
        equipment = self.equipments.get(record.equipment_id)  # 获取关联的设备对象
        if not equipment:  # 如果设备不存在
            print("关联的设备不存在！")
            return  # 退出方法
        
        return_date = input("请输入归还日期（YYYY-MM-DD，默认今天）：").strip()  # 获取用户输入的归还日期并去除首尾空格
        if not return_date:  # 如果没有输入归还日期
            return_date = datetime.now().strftime("%Y-%m-%d")  # 使用今天的日期
        
        remarks = input("请输入归还备注（可选）：").strip()  # 获取用户输入的归还备注并去除首尾空格
        
        record.actual_return = return_date  # 设置实际归还日期
        record.status = "已归还"  # 更新记录状态为已归还
        if remarks:  # 如果有归还备注
            record.remarks += f" | 归还备注：{remarks}"  # 将归还备注添加到原备注中
        
        equipment.status = "可用"  # 更新设备状态为可用
        
        print(f"设备 {equipment.name} 归还成功！")
        
        try:  # 尝试计算是否超期
            expected_date = datetime.strptime(record.expected_return, "%Y-%m-%d")  # 解析预期归还日期
            actual_date = datetime.strptime(return_date, "%Y-%m-%d")  # 解析实际归还日期
            if actual_date > expected_date:  # 如果实际归还日期晚于预期日期
                overdue_days = (actual_date - expected_date).days  # 计算超期天数
                print(f"注意：设备超期 {overdue_days} 天归还！")
        except:  # 如果日期解析失败
            pass  # 忽略错误
        
        self.save_data()  # 保存数据到文件
    
    def list_all_borrow_records(self):  # 定义列出所有借用记录的方法
        print("\n=== 所有借用记录 ===")
        if not self.borrow_records:  # 如果借用记录字典为空
            print("暂无借用记录。")
            return  # 退出方法
        
        print(f"共有 {len(self.borrow_records)} 条借用记录：")  # 打印借用记录总数
        for i, record in enumerate(self.borrow_records.values(), 1):  # 遍历所有借用记录，从1开始编号
            equipment_name = self.equipments.get(record.equipment_id, {}).name if record.equipment_id in self.equipments else "未知"  # 获取设备名称，如果设备不存在则显示"未知"
            print(f"{i}. {record} | 设备：{equipment_name}")  # 打印借用记录基本信息和设备名称
    
    def search_borrow_records(self):  # 定义查询借用记录方法
        print("\n=== 查询借用记录 ===")
        print("1. 按借用人查询")  # 显示查询选项1
        print("2. 按设备ID查询")  # 显示查询选项2
        print("3. 查询未归还记录")  # 显示查询选项3
        print("4. 查询超期记录")  # 显示查询选项4
        
        choice = input("请选择查询方式：").strip()  # 获取用户选择的查询方式并去除首尾空格
        
        if choice == '1':  # 如果选择按借用人查询
            borrower = input("请输入借用人：").strip()  # 获取用户输入的借用人并去除首尾空格
            results = [r for r in self.borrow_records.values() if borrower in r.borrower]  # 查找借用人中包含输入内容的记录
            self._display_borrow_results(results, f"借用人（{borrower}）")  # 显示查询结果
        
        elif choice == '2':  # 如果选择按设备ID查询
            equipment_id = input("请输入设备ID：").strip()  # 获取用户输入的设备ID并去除首尾空格
            results = [r for r in self.borrow_records.values() if r.equipment_id == equipment_id]  # 查找指定设备ID的记录
            self._display_borrow_results(results, f"设备ID（{equipment_id}）")  # 显示查询结果
        
        elif choice == '3':  # 如果选择查询未归还记录
            results = [r for r in self.borrow_records.values() if r.status == "借用中"]  # 查找状态为"借用中"的记录
            self._display_borrow_results(results, "未归还记录")  # 显示查询结果
        
        elif choice == '4':  # 如果选择查询超期记录
            today = datetime.now().strftime("%Y-%m-%d")  # 获取今天的日期字符串
            overdue_records = []  # 初始化超期记录列表
            for record in self.borrow_records.values():  # 遍历所有借用记录
                if record.status == "借用中":  # 如果记录状态为借用中
                    try:  # 尝试比较日期
                        if datetime.strptime(record.expected_return, "%Y-%m-%d") < datetime.strptime(today, "%Y-%m-%d"):  # 如果预期归还日期早于今天
                            overdue_records.append(record)  # 添加到超期记录列表
                    except:  # 如果日期解析失败
                        pass  # 忽略错误
            self._display_borrow_results(overdue_records, "超期记录")  # 显示查询结果
        
        else:  # 如果选择无效
            print("无效的选择！")
    
    def _display_borrow_results(self, results: List[BorrowRecord], search_type: str):  # 定义显示借用记录查询结果的私有方法
        if results:  # 如果有查询结果
            print(f"\n{search_type}查询结果（共{len(results)}条）：")  # 打印结果统计信息
            for i, record in enumerate(results, 1):  # 遍历结果列表，从1开始编号
                equipment_name = self.equipments.get(record.equipment_id, {}).name if record.equipment_id in self.equipments else "未知"  # 获取设备名称，如果设备不存在则显示"未知"
                print(f"{i}. 记录ID：{record.record_id} | 设备：{equipment_name} | 借用人：{record.borrower}")  # 打印记录基本信息
                print(f"    借用日期：{record.borrow_date} | 预计归还：{record.expected_return} | 状态：{record.status}")  # 打印日期和状态信息
                if record.actual_return:  # 如果有实际归还日期
                    print(f"    实际归还：{record.actual_return}")  # 打印实际归还日期
                if record.purpose:  # 如果有借用用途
                    print(f"    用途：{record.purpose}")  # 打印借用用途
                print()  # 打印空行分隔
        else:  # 如果没有查询结果
            print(f"未找到匹配的借用记录。")
    
    def show_statistics(self):  # 定义显示系统统计信息方法
        print("\n=== 系统统计信息 ===")
        print(f"设备总数：{len(self.equipments)}")  # 打印设备总数
        print(f"实验室总数：{len(self.laboratories)}")  # 打印实验室总数
        print(f"借用记录总数：{len(self.borrow_records)}")  # 打印借用记录总数
        
        if self.equipments:  # 如果有设备数据
            print("\n设备状态统计：")
            status_count = {}  # 初始化状态统计字典
            category_count = {}  # 初始化类别统计字典
            total_value = 0  # 初始化总价值
            
            for equipment in self.equipments.values():  # 遍历所有设备
                status_count[equipment.status] = status_count.get(equipment.status, 0) + 1  # 统计各状态的设备数量
                category_count[equipment.category] = category_count.get(equipment.category, 0) + 1  # 统计各类别的设备数量
                total_value += equipment.price  # 累加设备价格
            
            for status, count in status_count.items():  # 遍历状态统计结果
                print(f"  {status}：{count} 台")  # 打印每种状态的设备数量
            
            print("\n设备类别统计：")
            for category, count in category_count.items():  # 遍历类别统计结果
                print(f"  {category}：{count} 台")  # 打印每种类别的设备数量
            
            print(f"\n设备总价值：￥{total_value:.2f}")  # 打印设备总价值，保留两位小数
        
        if self.borrow_records:  # 如果有借用记录数据
            active_borrows = len([r for r in self.borrow_records.values() if r.status == "借用中"])  # 统计进行中的借用记录数量
            returned_borrows = len([r for r in self.borrow_records.values() if r.status == "已归还"])  # 统计已归还的借用记录数量
            
            print(f"\n借用状态统计：")
            print(f"  进行中：{active_borrows} 条")  # 打印进行中的借用记录数量
            print(f"  已归还：{returned_borrows} 条")  # 打印已归还的借用记录数量
            
            today = datetime.now().strftime("%Y-%m-%d")  # 获取今天的日期字符串
            overdue_count = 0  # 初始化超期记录计数
            for record in self.borrow_records.values():  # 遍历所有借用记录
                if record.status == "借用中":  # 如果记录状态为借用中
                    try:  # 尝试比较日期
                        if datetime.strptime(record.expected_return, "%Y-%m-%d") < datetime.strptime(today, "%Y-%m-%d"):  # 如果预期归还日期早于今天
                            overdue_count += 1  # 超期记录计数加1
                    except:  # 如果日期解析失败
                        pass  # 忽略错误
            
            if overdue_count > 0:  # 如果有超期记录
                print(f"  超期未还：{overdue_count} 条")  # 打印超期记录数量
    
    def export_lab_report(self):  # 定义导出实验室设备报告方法
        print("\n=== 导出实验室设备报告 ===")
        lab_id = input("请输入实验室ID：").strip()  # 获取用户输入的实验室ID并去除首尾空格
        
        if lab_id not in self.laboratories:  # 检查实验室ID是否存在
            print("实验室ID不存在！")
            return  # 如果不存在则退出方法
        
        laboratory = self.laboratories[lab_id]  # 获取实验室对象
        lab_equipments = [eq for eq in self.equipments.values() if eq.lab_id == lab_id]  # 获取该实验室的所有设备
        
        filename = f"lab_report_{lab_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"  # 生成报告文件名，包含实验室ID和当前时间戳
        
        try:  # 使用try-except结构处理可能的文件操作异常
            with open(filename, 'w', encoding='utf-8') as f:  # 以写入模式打开报告文件，指定UTF-8编码
                f.write("=" * 60 + "\n")  # 写入分隔线
                f.write(f"实验室设备报告\n")  # 写入报告标题
                f.write("=" * 60 + "\n\n")  # 写入分隔线和空行
                
                f.write(f"实验室信息：\n")  # 写入实验室信息标题
                f.write(f"  实验室ID：{laboratory.lab_id}\n")  # 写入实验室ID
                f.write(f"  实验室名称：{laboratory.name}\n")  # 写入实验室名称
                f.write(f"  实验室位置：{laboratory.location}\n")  # 写入实验室位置
                f.write(f"  管理员：{laboratory.manager}\n")  # 写入管理员信息
                f.write(f"  容量：{laboratory.capacity}\n")  # 写入实验室容量
                f.write(f"  描述：{laboratory.description}\n\n")  # 写入实验室描述和空行
                
                f.write(f"设备清单：\n")  # 写入设备清单标题
                if lab_equipments:  # 如果实验室有设备
                    total_value = 0  # 初始化总价值
                    status_count = {}  # 初始化状态统计字典
                    
                    for i, equipment in enumerate(lab_equipments, 1):  # 遍历实验室设备，从1开始编号
                        f.write(f"  {i}. {equipment.name}\n")  # 写入设备名称
                        f.write(f"     设备ID：{equipment.equipment_id}\n")  # 写入设备ID
                        f.write(f"     类别：{equipment.category}\n")  # 写入设备类别
                        f.write(f"     型号：{equipment.model}\n")  # 写入设备型号
                        f.write(f"     状态：{equipment.status}\n")  # 写入设备状态
                        f.write(f"     价格：￥{equipment.price}\n")  # 写入设备价格
                        f.write(f"     购买日期：{equipment.purchase_date}\n\n")  # 写入购买日期和空行
                        
                        total_value += equipment.price  # 累加设备价格
                        status_count[equipment.status] = status_count.get(equipment.status, 0) + 1  # 统计各状态的设备数量
                    
                    f.write(f"设备统计：\n")  # 写入设备统计标题
                    f.write(f"  设备总数：{len(lab_equipments)}\n")  # 写入设备总数
                    f.write(f"  设备总价值：￥{total_value:.2f}\n")  # 写入设备总价值，保留两位小数
                    f.write(f"  状态分布：\n")  # 写入状态分布标题
                    for status, count in status_count.items():  # 遍历状态统计结果
                        f.write(f"    {status}：{count} 台\n")  # 写入每种状态的设备数量
                else:  # 如果实验室没有设备
                    f.write("  暂无设备\n")  # 写入无设备提示
                
                f.write(f"\n报告生成时间：{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")  # 写入报告生成时间
                f.write("=" * 60 + "\n")  # 写入结束分隔线
            
            print(f"实验室设备报告已导出到文件：{filename}")  # 提示报告导出成功
        
        except Exception as e:  # 捕获所有异常
            print(f"报告导出失败：{e}")  # 打印错误信息
    
    def run(self):  # 定义系统主运行方法
        print("欢迎使用实验室设备管理系统！")
        
        while True:  # 无限循环，直到用户选择退出
            self.show_main_menu()  # 显示主菜单
            choice = input("\n请选择功能：").strip()  # 获取用户选择并去除首尾空格
            
            if choice == '1':  # 如果选择设备管理
                self.equipment_management()  # 调用设备管理方法
            elif choice == '2':  # 如果选择实验室管理
                self.laboratory_management()  # 调用实验室管理方法
            elif choice == '3':  # 如果选择借用管理
                self.borrow_management()  # 调用借用管理方法
            elif choice == '4':  # 如果选择统计查询
                self.statistics_management()  # 调用统计查询方法
            elif choice == '5':  # 如果选择保存数据
                self.save_data()  # 调用保存数据方法
            elif choice == '0':  # 如果选择退出系统
                print("感谢使用实验室设备管理系统！再见！")
                self.save_data()  # 退出前保存数据
                break  # 跳出循环，结束程序
            else:  # 如果选择无效
                print("无效的选择，请重新输入！")
    
    def show_main_menu(self):  # 定义显示主菜单方法
        print("\n" + "=" * 40)  # 打印分隔线
        print("实验室设备管理系统 - 主菜单")
        print("=" * 40)  # 打印分隔线
        print("1. 设备管理")  # 显示菜单选项1
        print("2. 实验室管理")  # 显示菜单选项2
        print("3. 借用管理")  # 显示菜单选项3
        print("4. 统计查询")  # 显示菜单选项4
        print("5. 保存数据")  # 显示菜单选项5
        print("0. 退出系统")  # 显示菜单选项0
        print("=" * 40)  # 打印分隔线
    
    def equipment_management(self):  # 定义设备管理子菜单方法
        while True:  # 无限循环，直到用户选择返回主菜单
            print("\n" + "-" * 30)  # 打印分隔线
            print("设备管理")
            print("-" * 30)  # 打印分隔线
            print("1. 添加设备")  # 显示子菜单选项1
            print("2. 删除设备")  # 显示子菜单选项2
            print("3. 修改设备")  # 显示子菜单选项3
            print("4. 查询设备")  # 显示子菜单选项4
            print("5. 显示所有设备")  # 显示子菜单选项5
            print("0. 返回主菜单")  # 显示子菜单选项0
            print("-" * 30)  # 打印分隔线
            
            choice = input("请选择功能：").strip()  # 获取用户选择并去除首尾空格
            
            if choice == '1':  # 如果选择添加设备
                self.add_equipment()  # 调用添加设备方法
            elif choice == '2':  # 如果选择删除设备
                self.delete_equipment()  # 调用删除设备方法
            elif choice == '3':  # 如果选择修改设备
                self.update_equipment()  # 调用修改设备方法
            elif choice == '4':  # 如果选择查询设备
                self.search_equipment()  # 调用查询设备方法
            elif choice == '5':  # 如果选择显示所有设备
                self.list_all_equipments()  # 调用显示所有设备方法
            elif choice == '0':  # 如果选择返回主菜单
                break  # 跳出循环，返回主菜单
            else:  # 如果选择无效
                print("无效的选择，请重新输入！")
    
    def laboratory_management(self):  # 定义实验室管理子菜单方法
        while True:  # 无限循环，直到用户选择返回主菜单
            print("\n" + "-" * 30)  # 打印分隔线
            print("实验室管理")
            print("-" * 30)  # 打印分隔线
            print("1. 添加实验室")  # 显示子菜单选项1
            print("2. 删除实验室")  # 显示子菜单选项2
            print("3. 修改实验室")  # 显示子菜单选项3
            print("4. 显示所有实验室")  # 显示子菜单选项4
            print("0. 返回主菜单")  # 显示子菜单选项0
            print("-" * 30)  # 打印分隔线
            
            choice = input("请选择功能：").strip()  # 获取用户选择并去除首尾空格
            
            if choice == '1':  # 如果选择添加实验室
                self.add_laboratory()  # 调用添加实验室方法
            elif choice == '2':  # 如果选择删除实验室
                self.delete_laboratory()  # 调用删除实验室方法
            elif choice == '3':  # 如果选择修改实验室
                self.update_laboratory()  # 调用修改实验室方法
            elif choice == '4':  # 如果选择显示所有实验室
                self.list_all_laboratories()  # 调用显示所有实验室方法
            elif choice == '0':  # 如果选择返回主菜单
                break  # 跳出循环，返回主菜单
            else:  # 如果选择无效
                print("无效的选择，请重新输入！")
    
    def borrow_management(self):  # 定义借用管理子菜单方法
        while True:  # 无限循环，直到用户选择返回主菜单
            print("\n" + "-" * 30)  # 打印分隔线
            print("借用管理")
            print("-" * 30)  # 打印分隔线
            print("1. 设备借用")  # 显示子菜单选项1
            print("2. 设备归还")  # 显示子菜单选项2
            print("3. 显示所有借用记录")  # 显示子菜单选项3
            print("4. 查询借用记录")  # 显示子菜单选项4
            print("0. 返回主菜单")  # 显示子菜单选项0
            print("-" * 30)  # 打印分隔线
            
            choice = input("请选择功能：").strip()  # 获取用户选择并去除首尾空格
            
            if choice == '1':  # 如果选择设备借用
                self.borrow_equipment()  # 调用设备借用方法
            elif choice == '2':  # 如果选择设备归还
                self.return_equipment()  # 调用设备归还方法
            elif choice == '3':  # 如果选择显示所有借用记录
                self.list_all_borrow_records()  # 调用显示所有借用记录方法
            elif choice == '4':  # 如果选择查询借用记录
                self.search_borrow_records()  # 调用查询借用记录方法
            elif choice == '0':  # 如果选择返回主菜单
                break  # 跳出循环，返回主菜单
            else:  # 如果选择无效
                print("无效的选择，请重新输入！")
    
    def statistics_management(self):  # 定义统计查询子菜单方法
        while True:  # 无限循环，直到用户选择返回主菜单
            print("\n" + "-" * 30)  # 打印分隔线
            print("统计查询")
            print("-" * 30)  # 打印分隔线
            print("1. 系统统计信息")  # 显示子菜单选项1
            print("2. 导出实验室设备报告")  # 显示子菜单选项2
            print("0. 返回主菜单")  # 显示子菜单选项0
            print("-" * 30)  # 打印分隔线
            
            choice = input("请选择功能：").strip()  # 获取用户选择并去除首尾空格
            
            if choice == '1':  # 如果选择系统统计信息
                self.show_statistics()  # 调用显示统计信息方法
            elif choice == '2':  # 如果选择导出实验室设备报告
                self.export_lab_report()  # 调用导出实验室设备报告方法
            elif choice == '0':  # 如果选择返回主菜单
                break  # 跳出循环，返回主菜单
            else:  # 如果选择无效
                print("无效的选择，请重新输入！")

def main():  # 定义主函数
    try:  # 使用try-except结构处理可能的异常
        system = LabEquipmentSystem()  # 创建实验室设备管理系统实例
        system.run()  # 运行系统主程序
    except KeyboardInterrupt:  # 捕获键盘中断异常（Ctrl+C）
        print("\n\n程序被用户中断，正在保存数据...")
        try:  # 尝试保存数据
            system.save_data()  # 调用保存数据方法
        except:  # 如果保存失败
            pass  # 忽略错误
        print("数据保存完成，程序退出。")
    except Exception as e:  # 捕获其他所有异常
        print(f"程序运行出错：{e}")  # 打印错误信息

if __name__ == "__main__":  # 如果当前脚本作为主程序运行
    main()  # 调用主函数
